#include "PacketProcessor.hpp"
#include "IncomingPacket.hpp"
#include "KieperException.hpp"
#include "ConnMgr.hpp"
#include "Log.hpp"

#include <iostream>

#include <boost/bind.hpp>

namespace kieper {
    using std::cout;

    using boost::thread;
    using boost::bind;
    using boost::mutex;
    using boost::lock_guard;

    PacketProcessor::PacketProcessor(ConnMgr& connMgr) : connMgr_(connMgr), isReady_(false) {}
    PacketProcessor::~PacketProcessor() {}
    
    void PacketProcessor::run() {
        try {
            LOG_TRACE("PacketProcessor thread started", 0);
            {
                lock_guard<mutex> guard(isReadyMtx_);
                isReady_ = true;
            }

            while(true) {
                processPacket(connMgr_.getNextPacket());
            }
        } catch (KieperException& e) {
            cout << "Exception caught!" << std::endl;
            cout << e.longMsg() << std::endl;
        }
    }

    void PacketProcessor::start() {
        processorThread_.reset(new thread(bind(&PacketProcessor::run, this)));
    }

    void PacketProcessor::processPacket(IncomingPacket* packet) {
        if (packet->getDirection() == Packet::DIRECTION_RESPONSE) {
            uint32_t packetId = packet->getPacketId();
            if (connMgr_.isThreadWaitingForResponse(packetId)) { 
                {
                    lock_guard<mutex> guard(*connMgr_.getMutex(packetId));
                    connMgr_.putResponsePacket(packet->getPacketId(), packet);
                }
                connMgr_.getCondition(packetId)->notify_one();
            }
        }
    }
    bool PacketProcessor::isReady() {
        return isReady_;
    }
}
